`timescale 1ns / 1ps
/*--------------------------------------------------------------------*\
FileName        : cbb_freqdivider.v
Author          ：hpy
Email           ：yuan_hp@qq.com
Date            ：2023年12月21日
Description     ：频率生成器
\*--------------------------------------------------------------------*/

/*--------- 实例化 ---------
cbb_freqdivider #(
	.IN_FREQ (50_000_000)  , // 输入时钟频率
    .OUT_FREQ(10_000_000)  , // 输出时钟频率
) u1 (
	.clk(),
	.rst_n(),
	.clkout()
); 
---------------------------*/
`timescale 1ns / 1ps
module cbb_freqdivider #(
    parameter	IN_FREQ	    = 50_000_000 , // 输入时钟频率
    parameter	OUT_FREQ	= 10_000_000  // 输出时钟频率
)(	
	input clk      ,     //输入信号
	input rst_n    ,
	output clkout   //输出信号，可以连接到LED观察分频的时钟
);

    localparam 	N	= IN_FREQ/OUT_FREQ   ;    //分频系数
	function integer clog2(input integer in);
		for(clog2 = 0; in; clog2 = clog2+1)
			in = in>>1;
	endfunction
	

	reg 	[clog2(N)-1:0]	cnt_p,cnt_n;     
	reg			clk_p,clk_n;     

	//上升沿触发时计数器的控制
	always @ (posedge clk )         
		begin
			if(!rst_n)
				cnt_p<=0;
			else if (cnt_p==(N-1))
				cnt_p<=0;
			else cnt_p<=cnt_p+1;             
		end

    always @ (posedge clk )
		begin
			if(!rst_n)
				clk_p<=0;
			else if (cnt_p<(N>>1))          
				clk_p<=0;
			else 
				clk_p<=1;           
		end

	always @ (negedge clk )
		begin
			if(!rst_n)
				cnt_n<=0;
			else if (cnt_n==(N-1))
				cnt_n<=0;
			else cnt_n<=cnt_n+1;
		end

	always @ (negedge clk)
		begin
			if(!rst_n)
				clk_n<=0;
			else if (cnt_n<(N>>1))  
				clk_n<=0;
			else 
				clk_n<=1;  
		end

        assign clkout = (N==1)?clk:(N[0])?(clk_p&clk_n):clk_p;      //条件判断表达式
                                                                    //当N=1时，直接输出clk
                                                                    //当N为偶数也就是N的最低位为0，N（0）=0，输出clk_p
                                                                    //当N为奇数也就是N最低位为1，N（0）=1，输出clk_p&clk_n。正周期多所以是相与
endmodule     